package swingxrcp.framework.server.environment;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import javax.servlet.ServletContext;

import org.springframework.context.ApplicationContext;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.web.context.ContextLoader;

import swingxrcp.framework.model.exception.ConfigurationException;
import swingxrcp.framework.server.action.ActionFactory;
import swingxrcp.framework.server.spring.FrameworkContextLoader;
import swingxrcp.framework.server.spring.SpringActionFactory;

/**
 * 环境
 *
 * @author liangfei
 * @since 2008-10-28
 */
public class Environment {

	private Environment() {}

	/**
	 * 应用配置
	 */
	public static final String APPLICATION_CONFIG = "/WEB-INF/application.properties";

	/**
	 * 模块配置目录
	 */
	public static final String MODULE_CONFIG_DIRECTORY = "META-INF/";

	/**
	 * 模块配置后缀
	 */
	public static final String MODULE_CONFIG_SUFFIX = ".module";

	// 服务模块搜索路径
	private static final String MODULE_SEARCH_PATH = "classpath*:" + MODULE_CONFIG_DIRECTORY + "**" + MODULE_CONFIG_SUFFIX;

	private static ContextLoader contextLoader;

	/**
	 * 初始化环境
	 * @param servletContext Servlet上下文
	 */
	public static ActionFactory initEnvironment(ServletContext servletContext) {
		Environment.servletContext = servletContext;
		Properties properties = new Properties();
		try {
			properties.load(servletContext.getResourceAsStream(APPLICATION_CONFIG));
		} catch (NullPointerException e) {
			throw new ConfigurationException("未配置：" + APPLICATION_CONFIG);
		} catch (IOException e) {
			throw new ConfigurationException("未配置：" + APPLICATION_CONFIG);
		}
		PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
		Map<String, Properties> modules = loadModules(resolver, MODULE_SEARCH_PATH);
		Environment.application = new Application(properties, modules);
		Environment.contextLoader = new FrameworkContextLoader();
		ApplicationContext applicationContext = Environment.contextLoader.initWebApplicationContext(getServletContext());
		return new SpringActionFactory(applicationContext);
	}

	// 加载模块
	private static Map<String, Properties> loadModules(PathMatchingResourcePatternResolver resolver, String path) {
		Map<String, Properties> modules = new HashMap<String, Properties>();
		try {
			Resource[] resources = resolver.getResources(path);
			for (Resource resource : resources) {
				String name = resource.getFilename();
				name = name.substring(0, name.length() - MODULE_CONFIG_SUFFIX.length());
				Properties module = new Properties();
				try {
					module.load(resource.getInputStream());
				} catch (NullPointerException e) {
					throw new ConfigurationException("加载配置失败，配置路径：" + resource.getURI(), e);
				} catch (IOException e) {
					throw new ConfigurationException("加载配置失败，配置路径：" + resource.getURI(), e);
				}
				modules.put(name, module);
			}
		} catch (IOException e) {
			throw new ConfigurationException("搜索配置失败！搜索路径：" + path, e);
		}
		return modules;
	}

	/**
	 * 销毁环境
	 */
	public static void destroyEnvironment() {
		if (Environment.contextLoader != null)
			Environment.contextLoader.closeWebApplicationContext(Environment.servletContext);
	}

	private static ServletContext servletContext;

	/**
	 * 获取Servlet上下文
	 *
	 * @return Servlet上下文
	 */
	public static ServletContext getServletContext() {
		return servletContext;
	}

	private static Application application;

	/**
	 * 获取当前应用信息
	 *
	 * @return 当前应用信息
	 */
	public static Application getApplication() {
		return application;
	}

	private static ThreadLocal<Module> modules = new ThreadLocal<Module>();

	/**
	 * 获取当前模块信息
	 *
	 * @return 当前模块信息
	 */
	public static Module getCurrentModule() {
		return modules.get();
	}

	/**
	 * 设置当前模块信息
	 *
	 * @param module 当前模块信息
	 */
	public static void setCurrentModule(Module module) {
		modules.set(module);
	}

}
